package org.helgoboss.one_filer_bundle_maven_plugin

import org.apache.maven.plugin._
import java.io.File
import org.scala_tools.maven.mojo.annotations._
import org.apache.maven.project.MavenProject

import org.helgoboss.scala_additions.Implicits._
import org.helgoboss.scala_additions.RichFile
import org.helgoboss.one_filer_ref_impl.OneFilerRefImpl
import org.helgoboss.bundle_project_facade.BundleProjectFacade
import org.helgoboss.project_data.ProjectData
import org.helgoboss.one_filer_template.OneFilerTemplate
import org.helgoboss.one_filer_template_manager.OneFilerTemplateManager
import org.helgoboss.basic_one_filer_template.BasicOneFilerTemplate

/**
 * Goal to generate Maven bundle projects from one-filers.
 */
@goal("generate")
@phase("process-sources")
class GenerateMojo extends AbstractMojo {
	
    @parameter
    @expression("${project}")
    @readOnly
    var project : MavenProject = _
    
    @parameter
    @expression("${project.basedir}/src/main/one-filers")
    @required
    var sourceDir: File = _
    
    @parameter
    @expression("${project.basedir}/target")
    @required
    var targetDir: File = _
    
    @parameter
    var templates: Array[String] = Array()
    
    
    private val bundleProjectFacade = new BundleProjectFacade



    @throws(classOf[MojoExecutionException])
    override def execute {
        val templateManager = new OneFilerTemplateManager
        templateManager.registerTemplate(BasicOneFilerTemplate)
        templates.foreach { templateClassName =>
            val template = getTemplateObject(templateClassName)
            templateManager.registerTemplate(template)
        }
        
        val oneFiler = new OneFilerRefImpl(lookupTemplate = templateManager.findTemplate _)
        if (sourceDir.isDirectory) {
            val projectDatas = oneFiler.extractProjectDatas(sourceDir)
            bundleProjectFacade.generateBundleProjects(projectDatas, targetDir)
        } else {
            throw new MojoExecutionException("sourceDir [" + sourceDir + "] doesn't exist or is no directory")
        }
    }
    
    private def getTemplateObject(templateClassName: String) = {
        try {
            val templateClass = Class.forName(templateClassName)
            templateClass.newInstance.asInstanceOf[OneFilerTemplate]
        } catch {
            case e: InstantiationException =>
                /* Assume it's a Scala object */
                val templateObjectClassName = templateClassName + "$"
                val templateObjectClass = Class.forName(templateObjectClassName)
                val moduleField = templateObjectClass.getField("MODULE$")
                moduleField.setAccessible(true)
                moduleField.get(templateObjectClass).asInstanceOf[OneFilerTemplate]
        }
    }
}